package com.jimikongjian.service;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.jimikongjian.dao.IUser;
import com.jimikongjian.dao.IUserInfo;
import com.jimikongjian.models.*;
import com.jimikongjian.service.base.IUserService;
import com.jimikongjian.service.message.ResponseMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Type;
import java.util.*;

/**
 * Created by baidu on 17/2/14.
 * @author fuxiuyang
 */
@Service("userService")
public class UserService implements IUserService {

    @Autowired
    @Qualifier("iUserImpl")
    private IUser iUser;

    @Autowired
    @Qualifier("iUserInfoImpl")
    private IUserInfo iUserInfo;

    @Autowired
    @Qualifier("mailService")
    private MailService mailService;

    @Autowired
    @Qualifier("codeService")
    private CodeService codeService;

    @Autowired
    @Qualifier("redisService")
    private RedisService redisService;

    @Autowired
    DefaultKaptcha defaultKaptcha;

    @Autowired
    @Qualifier("tokenService")
    private TokenService tokenService;

    @Autowired
    @Qualifier("responseMessageService")
    private ResponseMessageService responseMessageService;


    /**
     * 密码的长度，默认是md5加密后的长度，即为32位
     */
    @Value("${password.length}")
    private Integer passwordLength;

    /**
     * 注册验证码在redis存活的时长
     */
    @Value("${code.registerExpireTime}")
    private Long registerExpireTime;

    /**
     * 密码重置验证码在redis存活的时长
     */
    @Value("${code.resetPwExpireTime}")
    private Long resetPwExpireTime;

    /**
     * 密码重置验证码在redis存活的时长
     */
    @Value("${code.loginExpireTime}")
    private Long loginExpireTime;




    /**
     * 用户登录
     * @param email
     * @param password
     * @return 查找成功就返回成功的信息码,否则返回错误失败码
     */
    public ResponseMessage login(String email, String password, String uuid, String code){
        if (!mailService.isEmail(email))
            return responseMessageService.makeMessage(Message.EMAIL_FORMAT_ERROR);
        //   验证是否存在验证码已经验证码是否正确
        if (!redisService.exists(uuid) || !redisService.get(uuid).equals(code))
            return responseMessageService.makeMessage(Message.VERIFICATION_CODE_ERROR);
        redisService.remove(uuid);
        User user = iUser.getUserByEmail(email);
        if (user != null ){
            if(user.getPassword().equals(password)) {
                // 封装返回体
                Token token = tokenService.createToken(email);
                UserInfo userInfo =  iUserInfo.getUserInfoByUserId(user.getId());
                ArrayList arrayList = new ArrayList();
                arrayList.add(token);
                arrayList.add(userInfo);
                return responseMessageService.makeMessage(arrayList, Message.SUCCESS);
            }
            return responseMessageService.makeMessage(Message.PASSWORD_ERROR);
        }
        return responseMessageService.makeMessage(Message.NO_HAVE_USER);
    }

    /**
     * 用来生成登录验证码图片，并且将图片压缩成base64,返回给前端
     * @return
     * @throws Exception
     */
    public ResponseMessage getCodeImage() throws Exception{
        byte[] captchaChallengeAsJpeg = null;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        String uuid = "";
        try {
            //生产验证码字符串
            String createText = defaultKaptcha.createText();
            uuid = UUID.randomUUID().toString();
            redisService.set(uuid, createText, loginExpireTime);
            //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
        } catch (IllegalArgumentException e) {
            return responseMessageService.makeMessage(Message.SYSTEM_ERROR);
        }

        //定义response输出类型为image/jpeg类型，使用response输出流输出图片的byte数组
        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
        BASE64Encoder base64Encoder = new BASE64Encoder();
        String imageData = base64Encoder.encode(captchaChallengeAsJpeg);
        HashMap<String, String> result = new HashMap<>();
        result.put("image", imageData);
        result.put("uuid", uuid);
        return responseMessageService.makeMessage(result, Message.SUCCESS);
    }

    /**
     * 用户登出
     *
     * @param email
     * @return 查找成功就返回成功的信息码, 否则返回错误失败码
     */
    public void logout(String email) {
        tokenService.deleteToken(email);
    }

    /**
     * 用户注册
     * @param email
     * @param password
     * @param nick 用户昵称
     * @param code 验证码
     * @return 插入成功就返回成功的信息码,否则返回错误失败码
     */
    @Transactional
    public ResponseMessage register(String email, String password, String nick, String code){
        //这里应该进行事务控制,如果有一个插入不成功,则数据库进行回滚

        // 验证邮箱格式
        if (!mailService.isEmail(email))
            return responseMessageService.makeMessage(Message.EMAIL_FORMAT_ERROR);

        // 验证密码的长度是否合规
        if (password.length() != passwordLength)
            return responseMessageService.makeMessage(Message.PASSWORD_FORMAT_ERROR);

        //   验证是否存在验证码已经验证码是否正确
        if (!redisService.exists(email) || !redisService.get(email).equals(code))
            return responseMessageService.makeMessage(Message.VERIFICATION_CODE_ERROR);

        if(!hasEmail(email)){
            User user = new User();
            user.setEmail(email);
            user.setPassword(password);
            if(iUser.insertUser(email, password)){
                int userId = iUser.getUserIdByEmail(email);
                UserInfo userInfo = new UserInfo();
                userInfo.setUserId(userId);
                userInfo.setUserEmail(email);
                userInfo.setNick(nick);
                if(iUserInfo.insertUserInfo(userInfo)){
                    redisService.remove(email);
                    return responseMessageService.makeMessage(Message.SUCCESS);
                }
                return responseMessageService.makeMessage(Message.SYSTEM_ERROR);
            }
        }
        return responseMessageService.makeMessage(Message.EMAIL_HAVE_BE_REGISTER);
    }

    /**
     * 重置密码第一步，验证邮箱验证码是否和系统存储的一样
     *
     * @param email
     * @param code
     * @return
     */
    @Override
    public ResponseMessage updatePassWord01(String email, String code) {
        // 验证邮箱格式
        if (!mailService.isEmail(email))
            return responseMessageService.makeMessage(Message.EMAIL_FORMAT_ERROR);

        //   验证是否存在验证码已经验证码是否正确
        if (!redisService.exists(email) || !redisService.get(email).equals(code))
            return responseMessageService.makeMessage(Message.VERIFICATION_CODE_ERROR);

        /**
         * 生产uuid 作为用户通过重置密码第一步的凭证
         */
        UUID uuid = UUID.randomUUID();

        redisService.set(email, uuid.toString(), resetPwExpireTime);
        HashMap<String, String> map = new HashMap<>();
        map.put("code", uuid.toString());
        return  responseMessageService.makeMessage(map, Message.SUCCESS);
    }

    /**
     * 重置密码第二步，将新密码写入数据库中，写入之前，使用code验证该调用已经通过了第一步。
     *
     * @param email
     * @param password
     * @param code
     * @return
     */
    @Override
    public ResponseMessage updatePassWord02(String email, String password, String code) {
        // 验证邮箱格式
        if (!mailService.isEmail(email))
            return responseMessageService.makeMessage(Message.EMAIL_FORMAT_ERROR);

        // 验证密码的长度是否合规
        if (password.length() != passwordLength)
            return responseMessageService.makeMessage(Message.PASSWORD_FORMAT_ERROR);

        //   验证是否存在验证码已经验证码是否正确
        if (!redisService.exists(email) || !redisService.get(email).equals(code))
            return responseMessageService.makeMessage(Message.VERIFICATION_CODE_ERROR);

        iUser.updateUserPassword(email, password);
        return responseMessageService.makeMessage(Message.SUCCESS);
    }

    /**
     * 获取用户信息
     * @param id
     * @param userId
     * @return
     */
    public ResponseMessage getUserInfo(int id, int userId){
        if (hasUser(id) && hasUser(userId)){
            if (id == userId){
                List<UserInfo> userInfo = iUserInfo.getUserInfoListByUserId(userId);
                return responseMessageService.makeMessage(userInfo, Message.SUCCESS);
            }else {
                UserInfo userInfo = iUserInfo.getUserInfoByUserId(userId);
                if (userInfo.getShow() == UserInfo.SHOW){
                    return responseMessageService.makeMessage(userInfo, Message.SUCCESS);
                }
                return responseMessageService.makeMessage(Message.NO_PERMISSION_ERROR);
            }
        }
        return responseMessageService.makeMessage(Message.NO_HAVE_USER);
    }

    /**
     * 更新用户信息
     *
     * @param userInfo
     * @return
     */
    public ResponseMessage updateUserInfo(UserInfo userInfo) {
        if(hasUser(userInfo.getUserId())){
            iUserInfo.updateUserInfo(userInfo);
            return responseMessageService.makeMessage(Message.SUCCESS);
        }
        return responseMessageService.makeMessage(Message.NO_HAVE_USER);
    }

    /**
     * 向邮箱发送验证码
     * @param email
     * @return
     */
    public ResponseMessage sendRegisterMail(String email){
        String code = codeService.getCode();
        if (redisService.set(email, code, registerExpireTime)){
            mailService.sendRegisterMail(email, code);
            return responseMessageService.makeMessage(Message.SUCCESS);
        }
        return responseMessageService.makeMessage(Message.SYSTEM_ERROR);
    }

    /**
     * 向邮箱发送密码重置验证码
     *
     * @param email
     * @return
     */
    @Override
    public ResponseMessage sendResetPwMail(String email) {
        if (hasEmail(email)){
            String code = codeService.getCode();
            if (redisService.set(email, code, resetPwExpireTime)){
                mailService.sendresetPwMail(email, code);
                return responseMessageService.makeMessage(Message.SUCCESS);
            }
            return responseMessageService.makeMessage(Message.SYSTEM_ERROR);
        }
        return responseMessageService.makeMessage(Message.NO_HAVE_USER);

    }

    /**
     * 验证邮箱是否已经被注册
     * @param email
     * @return
     */
    public ResponseMessage isRegister(String email){
        if (mailService.isEmail(email)){
            if (hasEmail(email)){
                return responseMessageService.makeMessage(Message.EMAIL_HAVE_BE_REGISTER);
            }
            return responseMessageService.makeMessage(Message.SUCCESS);
        }
        return responseMessageService.makeMessage(Message.EMAIL_FORMAT_ERROR);
    }


    /**
     * 查找数据库中是否含有该用户
     * @param email
     * @return 如果含有则返回true,否则返回false
     */
    public boolean hasEmail(String email){
        if(iUser.getUserByEmail(email) != null){
            return true;
        }
        return false;
    }

    /**
     * 查找数据库中是否含有该用户
     *
     * @param userId
     * @return 如果含有则返回true, 否则返回false
     */
    public boolean hasUser(int userId) {
        if (iUser.getUserListById(userId) != null &&iUser.getUserListById(userId).size() > 0){
            return true;
        }
        return false;
    }

}
